package org.wattdepot.cli.commands;

import java.util.List;
import javax.xml.datatype.XMLGregorianCalendar;
import org.wattdepot.client.BadXmlException;
import org.wattdepot.client.MiscClientException;
import org.wattdepot.client.NotAuthorizedException;
import org.wattdepot.client.ResourceNotFoundException;
import org.wattdepot.client.WattDepotClient;
import org.wattdepot.util.tstamp.Tstamp;

/**
 * This class contains a command that prints out how much carbon or energy
 * is emitted by a source for a whole day.
 * It uses a sampling interval to calculate this number.
 * @author David Mau
 */
public class TotalSamplingCommand implements WattDepotCliCommand {
  // Default client-server connection to use unless given one.
  private WattDepotClient client = new WattDepotClient(debug);

  /**
   * This constructor makes sure that the client really is connected to the server.
   * 
   * @param anotherClient Specifies if the user wants to use another WattDepot server
   * other than the default simulation one.
   */
  public TotalSamplingCommand( String anotherClient ) {
    // If another client is provided
    if ( anotherClient != null ) {
      client = new WattDepotClient( anotherClient );
    }
    
    // Stop right away if we cannot contact server.
    if (!client.isHealthy()) {
      System.out.println("Failed to connect to " + client.getWattDepotUri());
      return;
    }
    // Indicate successful connection.
    //System.out.println("Connected to " + client.getWattDepotUri());
  }
  
  /**
   * This method returns a double that reflects how much power is generated or consumed by a source
   * at a given time stamp.
   * 
   * Created by David Mau.
   * 
   * @param args A list of arguments given to this command.
   * @return A String in MegaWatts of how much carbon or energy was generated.
   */
  public String doCommand( List<String> args) {
    String output;
    
    if ( args.size() > 4 ) {
      output = tooManyArguments;
      output = output.concat( cr );
      return output;
    }
    if ( args.size() < 4 ) {
      output = missingArguments;
      output = output.concat( cr );
      return output;
    }
    
    String type = args.get( 0 );
    String source = args.get( 1 );
    String day = args.get( 2 );
    String minutes = args.get( 3 );
    
    double doubleOutput;
    int interval;

    String startTime = day;
    startTime = startTime.concat("T00:00:00.000-10:00");
    String endTime = day;
    endTime = endTime.concat("T23:59:00.000-10:00");

    try {
      interval = Integer.valueOf(minutes);
    }
    catch (NumberFormatException e) {
      output = intervalNotNumber;
      output = output.concat(e.toString());
      output = output.concat(cr);
      return output;
    }

    // If the converted integer is negative or zero, return an error.
    if (interval <= 0) {
      output = intervalNegativeOrZero;
      output = output.concat(cr);
      return output;
    }

    // Convert the time stamp Strings into an XML ones.
    XMLGregorianCalendar xmlTimeStart = null;
    try {
      xmlTimeStart = Tstamp.makeTimestamp(startTime);
    }
    catch (Exception e) {
      output = badTimeStamp;
      output = output.concat(e.toString());
      output = output.concat(cr);
      return output;
    }
    XMLGregorianCalendar xmlTimeEnd = null;
    try {
      xmlTimeEnd = Tstamp.makeTimestamp(endTime);
    }
    catch (Exception e) {
      output = badTimeStamp;
      output = output.concat(e.toString());
      output = output.concat(cr);
      return output;
    }

    if (type.compareTo("carbon") == 0) {
      // Try to collect data from the server using the source and converted time stamp.
      try {
        doubleOutput = client.getCarbonEmitted(source, xmlTimeStart, 
            xmlTimeEnd, interval);
        output = String.valueOf( doubleOutput );
        output = output.concat( " pounds" );
        output = output.concat(cr);
      }
      catch (NotAuthorizedException e) {
        output = notAuthorized;
        output = output.concat(e.toString());
        output = output.concat(cr);
        return output;
      }
      catch (ResourceNotFoundException e) {
        output = resourceNotFound;
        output = output.concat(e.toString());
        output = output.concat(cr);
        return output;
      }
      catch (BadXmlException e) {
        output = badXml;
        output = output.concat(e.toString());
        output = output.concat(cr);
        return output;
      }
      catch (MiscClientException e) {
        output = miscClient;
        output = output.concat(e.toString());
        output = output.concat(cr);
        return output;
      }
    }
    else if (type.compareTo("energy") == 0) {
      // Try to collect data from the server using the source and converted time stamp.
      try {
        doubleOutput = client.getEnergyGenerated(source, xmlTimeStart, 
            xmlTimeEnd, interval) / 1000000;
        output = String.valueOf( doubleOutput );
        output = output.concat( " MegaWatt-Hours" );
        output = output.concat(cr);
      }
      catch (NotAuthorizedException e) {
        output = notAuthorized;
        output = output.concat(e.toString());
        output = output.concat(cr);
        return output;
      }
      catch (ResourceNotFoundException e) {
        output = resourceNotFound;
        output = output.concat(e.toString());
        output = output.concat(cr);
        return output;
      }
      catch (BadXmlException e) {
        output = badXml;
        output = output.concat(e.toString());
        output = output.concat(cr);
        return output;
      }
      catch (MiscClientException e) {
        output = miscClient;
        output = output.concat(e.toString());
        output = output.concat(cr);
        return output;
      }
    }
    else {
      output = carbonOrEnergy;
      output = output.concat(cr);
      return output;
    }
    
    return output;
  }
}
